/******************************************************************************/
/* @ All Rights Reserved Copyright (C) 2014 broada,Ltd.                       */
/*                                                                            */
/*  NAME      = postgresql_request.c                                          */
/*  NOTE      = postgresql请求解析                                            */
/*  DATE      = 2016/01/06 by zhengxd                                         */
/******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <math.h>
#include <stdint.h>
#include <limits.h>

extern void *g_p_apm_context;

#include "postgresql_core.h"
#include "postgresql_comm.h"

/*******************************************************************************
*  FUNC     :  上报request数据
*  ARGS     :  p_st_conn (链接信息)
*           :  p_st_private (私有信息)
*           :  p_st_hash_report (hash)
*  RTN      :
*  NOTE     :  p_st_private肯定不为NULL
*******************************************************************************/
FR_STATIC int __postgresql_report_req(Conntrack *p_st_conn
                                  , L7session_postgresql_private *p_st_private
                                  , Frhash_header *p_st_hash_report)
{
    int i_ret = FR_SUCC;
    Frreport_body_data *p_st_report_body = NULL;
    L7_req_postgresql *p_st_req = p_st_private->p_st_req;
    Postgresql_req_cmd *p_st_command = NULL;
    Frlist_node *p_st_node = NULL;

    p_st_node = FRLIST_FIRST_NODE(&p_st_req->st_command_lst);
    while (p_st_node)
    {
        p_st_command = (Postgresql_req_cmd *)FRLIST_GET_NODE_DATA(p_st_node);

        i_ret = frdb_set_resultset_req2(p_st_command->p_st_resultset
                                       , p_st_command->i_packet_len
                                       , &(p_st_command->st_start_timestamp)
                                       , &(p_st_command->st_end_timestamp));
       if (i_ret != FR_SUCC)
       {
            frdbg("update resultset failed\n");
            return APM_L7_ANALYZE_FAIL;
       }

        if (p_st_command->i_report_flg == FR_YES)
        {
            /* 创建report body */
            p_st_report_body = postgresql_new_report_body(p_st_conn, p_st_private->p_st_sess);
            /* 创建report body失败时，不释放做成的request */
            if (p_st_report_body == NULL)
            {
                frdbg("call postgresql_new_report_body failed!\n");
                return APM_L7_ANALYZE_FAIL;
            }

            /* 上报request数据 */
            i_ret = frdb_report_req2(p_st_conn, p_st_hash_report
                                     , p_st_command->p_st_statement
                                     , p_st_command->p_st_resultset
                                     , &p_st_report_body);
            /* 上报request数据失败时，不释放做成的request */
            if (i_ret != FR_SUCC)
            {
                frdbg("frdb_report_req2 failed!\n");
                frreport_body_free(&p_st_report_body);
                return APM_L7_ANALYZE_SUCC;
            }
        }
        p_st_node = FRLIST_NEXT_NODE(p_st_node);
    }

    return APM_L7_ANALYZE_SET_REQ(APM_L7_ANALYZE_SUCC);
}

/*******************************************************************************
*  FUNC:  解析startup
*  ARGS:  p_st_conn(connect信息)
*      :  p_st_private(私有信息)
*      :  pp_cursor_str(cursor)
*      :  i_packet_len(packet长度)
*      :  i_report_flg(上报flag)
*      :  st_start_timestamp(start time)
*      :  st_end_timestamp(end time)
*  RTN :  FR_SUCC       (succ)
*         FR_FAIL       (fail)
*  NOTE:
*******************************************************************************/
FR_STATIC int __postgresql_update_statement(Conntrack *p_st_conn
                                         , L7session_postgresql_private *p_st_private
                                         , char **pp_cursor_str
                                         , int i_packet_len
                                         , int i_report_flg
                                         , struct timeval st_start_timestamp
                                         , struct timeval st_end_timestamp)
{
    unsigned long ul_req_sequence = 0;
    L7_req_postgresql *p_st_req = p_st_private->p_st_req;
    Postgresql_req_cmd *p_st_command = p_st_req->p_st_command_pre;
    Sql_resultset *p_st_resultset = NULL;
    Sql_statement *p_st_statement = NULL;
    Frlist_node *p_hash_node = NULL;
    Frlist_node *p_st_node = NULL;
    char *p_cursor_str = *pp_cursor_str;

    /* 游标存在 */
    if (p_cursor_str)
    {
        /* 前一个游标一致 */
        if (p_st_command && p_st_command->p_cursor_str
            && strcmp(p_st_command->p_cursor_str, p_cursor_str) == 0)
        {
            p_st_command->i_packet_len += i_packet_len;
            p_st_command->i_report_flg = i_report_flg;
            p_st_command->st_end_timestamp = st_end_timestamp;
        }
        /* 前后游标不一致,需要从hash中查找对应的statement */
        else
        {
            p_hash_node = frhash2_getStr(p_st_private->p_hash_prepare
                                         , p_cursor_str, strlen(p_cursor_str));
            /* 取得statement */
            p_st_statement = (Sql_statement *)FRLIST_GET_NODE_DATA(p_hash_node);
            if (p_st_statement == NULL)
            {
                return FR_FAIL;
            }
            /* 创建resultset */
            ul_req_sequence = frct_seq_increase(p_st_conn);
            p_st_resultset = frdb_create_resultset(ul_req_sequence);
            if (p_st_resultset == NULL)
            {
                return FR_FAIL;
            }

            /* 创建command */
            p_st_command = (Postgresql_req_cmd *)frmalloc(sizeof(Postgresql_req_cmd));
            if (p_st_command == NULL)
            {
                frdb_resultset_free(&p_st_resultset);
                return FR_FAIL;
            }
            memset(p_st_command, 0x0, sizeof(Postgresql_req_cmd));
            /* 追加command到list */
            p_st_node = frlist_node_create(p_st_command);
            if (p_st_node == NULL)
            {
                frfree(p_st_command);
                frdb_resultset_free(&p_st_resultset);
                return FR_FAIL;
            }
            /* 设置command */
            p_st_command->i_new_flg = FR_NO;
            p_st_command->p_st_statement = p_st_statement;
            p_st_command->p_st_resultset = p_st_resultset;
            p_st_command->i_packet_len = i_packet_len;
            p_st_command->i_report_flg = i_report_flg;
            p_st_command->st_start_timestamp = st_start_timestamp;
            p_st_command->st_end_timestamp = st_end_timestamp;
            p_st_command->p_cursor_str = p_cursor_str;
            *pp_cursor_str = NULL;
            p_st_req->p_st_command_pre = p_st_command;
            frlist_push(&p_st_req->st_command_lst, p_st_node);
            return FR_SUCC;
        }
    }
    /* 游标不存在 */
    else
    {
        if (p_st_command == NULL)
        {
            frdbg("just skip\n");
            return FR_SUCC;
        }
        p_st_command->i_packet_len += i_packet_len;
        p_st_command->i_report_flg = i_report_flg;
        p_st_command->st_end_timestamp = st_end_timestamp;
    }

    /* 创建resultset */
    if (p_st_command->p_st_resultset == NULL)
    {
        ul_req_sequence = frct_seq_increase(p_st_conn);
        p_st_command->p_st_resultset = frdb_create_resultset(ul_req_sequence);
        if (p_st_command->p_st_resultset == NULL)
        {
            return FR_FAIL;
        }
    }
    return FR_SUCC;
}

/*******************************************************************************
*  FUNC:  解析startup
*  ARGS:  p_st_data (betebuff)
*      :  i_packet_len(startup长度，包括长度位)
*      :  pp_user(用户名)
*      :  pp_database(数据库名称)
*  RTN :  APM_L7_ANALYZE_SUCC       (succ)
*         APM_L7_ANALYZE_TODO       (need more)
*         APM_L7_ANALYZE_FAIL       (fail)
*  NOTE:
*******************************************************************************/
FR_STATIC int __postgresql_parse_startup(Frbyte_Packet *p_st_data
                                      , int i_packet_len
                                      , char **pp_user
                                      , char **pp_database)
{
    int i_ret = FR_SUCC;
    char *p_name = NULL;
    char *p_user = NULL;
    char *p_database = NULL;
    i_packet_len -= 4;

    /* 长度check */
    if (i_packet_len > bytebuff_remaining(p_st_data))
    {
        frdbg("need more data!\n");
        return APM_L7_ANALYZE_TODO;
    }
    i_packet_len -= 4;
    /* skip protocol version number */
    i_ret = bytebuff_skip(p_st_data, 4);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    while (i_packet_len)
    {
        i_ret = postgresql_get_string(p_st_data, &i_packet_len, &p_name);
        if (i_ret != FR_SUCC)
        {
            goto error;
        }
        if (p_name == NULL)
        {
            /* startup结束标识 */
            if (i_packet_len == 0)
            {
                *pp_user = p_user;
                *pp_database = p_database;
                return APM_L7_ANALYZE_SUCC;
            }
            /* name不能为NULL */
            else
            {
                goto error;
            }
        }
        else if (strcasecmp(p_name, "user") == 0)
        {
            if (p_user)
            {
                frdbg("double user!\n");
                goto error;
            }
            i_ret = postgresql_get_string(p_st_data, &i_packet_len, &p_user);
        }
        else if (strcasecmp(p_name, "database") == 0)
        {
            if (p_database)
            {
                frdbg("double p_database!\n");
                goto error;
            }
            i_ret = postgresql_get_string(p_st_data, &i_packet_len, &p_database);
        }
        else
        {
            i_ret = postgresql_skip_string(p_st_data, &i_packet_len);
        }

        frfree(p_name);
        p_name = NULL;
        if (i_ret != FR_SUCC)
        {
            goto error;
        }
    }

    goto error;

error:
    if (p_name)
    {
        frfree(p_name);
    }
    if (p_user)
    {
        frfree(p_user);
    }
    if (p_database)
    {
        frfree(p_database);
    }
    return APM_L7_ANALYZE_FAIL;
}

/*******************************************************************************
*  FUNC:  解析password
*  ARGS:  p_st_private (postgresql私有数据)
*      :  i_packet_len(packet长度，包括type位+长度位)
*  RTN :  APM_L7_ANALYZE_SUCC       (succ)
*         APM_L7_ANALYZE_TODO       (need more)
*         APM_L7_ANALYZE_FAIL       (fail)
*  NOTE:  i_packet_len必须大于等于与5
*******************************************************************************/
FR_STATIC int __postgresql_parse_password(L7session_postgresql_private *p_st_private
                                       , int i_packet_len
                                       , int *p_i_end_flg)
{
    int i_ret = FR_SUCC;
    Frbyte_Packet *p_st_data = p_st_private->p_st_fragment->p_st_data;
    int i_left_len = i_packet_len - 5;

    /* 长度check */
    if (i_left_len > bytebuff_remaining(p_st_data))
    {
        frdbg("need more data!\n");
        i_ret = bytebuff_set_skip(p_st_data, i_left_len - bytebuff_remaining(p_st_data));
        if (i_ret != FR_SUCC)
        {
            return APM_L7_ANALYZE_FAIL;
        }
        return APM_L7_ANALYZE_TODO;
    }
    /* 单个passwor message是单独作为一个请求的 */
    else if (i_left_len == bytebuff_remaining(p_st_data))
    {
        bytebuff_skip(p_st_data, i_left_len);
        p_st_private->p_st_req->i_req_type = POSTGRESQL_TP_PASSWORD_MSG;
        *p_i_end_flg = FR_YES;
        return APM_L7_ANALYZE_SUCC;
    }
    else
    {
        frdbg("format incorrect!\n");
        return APM_L7_ANALYZE_FAIL;
    }
}

/*******************************************************************************
*  FUNC:  解析parse
*  ARGS:  p_st_private (postgresql私有数据)
*      :  i_packet_len(packet长度，包括type位+长度位)
*  RTN :  APM_L7_ANALYZE_SUCC       (succ)
*         APM_L7_ANALYZE_TODO       (need more)
*         APM_L7_ANALYZE_FAIL       (fail)
*  NOTE:  i_packet_len必须大于等于与5
*******************************************************************************/
FR_STATIC int __postgresql_parse_parse(L7session_postgresql_private *p_st_private
                                    , int i_packet_len)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    int i_param_count = 0;
    int i_left_len = i_packet_len - 5;
    L7_fragment_postgresql *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;
    L7_req_postgresql *p_st_req = p_st_private->p_st_req;
    Postgresql_req_cmd *p_st_command = NULL;
    Frlist_node *p_st_node = NULL;
    Sql_statement *p_st_statement = NULL;
    char *p_cursor_str = NULL;
    char *p_sql = NULL;

    /* 长度check */
    if (i_left_len > bytebuff_remaining(p_st_data))
    {
        frdbg("need more data!\n");
        return APM_L7_ANALYZE_TODO;
    }

    /* 取得游标标识字符串 */
    i_ret = postgresql_get_string(p_st_data, &i_left_len, &p_cursor_str);
    if (i_ret != FR_SUCC)
    {
        frdbg("get cursor string failed!\n");
        return APM_L7_ANALYZE_FAIL;
    }
    /* 取得sql语句 */
    i_ret = postgresql_get_string(p_st_data, &i_left_len, &p_sql);
    if (i_ret != FR_SUCC)
    {
        frdbg("get sql statement failed!\n");
        goto error;
    }
    /* 取得参数个数 */
    i_ret = postgresql_get_short(p_st_data, &i_left_len, &i_param_count);
    if (i_ret != FR_SUCC || i_param_count < 0)
    {
        frdbg("get parameter count failed!\n");
        goto error;
    }
    if (i_left_len != i_param_count * 4)
    {
        frdbg("format incorrect!\n");
        goto error;
    }
    /* skip paramemter formats */
    bytebuff_skip(p_st_data, i_left_len);

    /* create statement */
    p_st_statement = frdb_create_statement();
    if (p_st_statement == NULL)
    {
        frdbg("create statement failed!\n");
        goto error;
    }
    /* 设置sql statement */
    frdb_set_sql(p_st_statement, p_sql);
    p_sql = NULL;

    /* 创建一个command信息结构体 */
    p_st_command = (Postgresql_req_cmd *)frmalloc(sizeof(Postgresql_req_cmd));
    if (p_st_command == NULL)
    {
        frdbg("create command failed!\n");
        goto error;
    }
    memset(p_st_command, 0x0, sizeof(Postgresql_req_cmd));
    p_st_command->i_new_flg = FR_YES;
    p_st_command->p_cursor_str = p_cursor_str;
    p_cursor_str = NULL;
    p_st_command->p_st_statement = p_st_statement;
    p_st_statement = NULL;
    p_st_command->i_packet_len = i_packet_len;
    p_st_command->st_start_timestamp = p_st_fragment->st_start_timestamp;
    p_st_command->st_end_timestamp = p_st_fragment->st_end_timestamp;

    /* 追加到command list中 */
    p_st_node = frlist_node_create(p_st_command);
    if (p_st_node == NULL)
    {
        frdbg("create command node failed!\n");
        goto error;
    }
    frlist_push(&p_st_req->st_command_lst, p_st_node);
    p_st_req->p_st_command_pre = p_st_command;

    return APM_L7_ANALYZE_SUCC;

error:
    if (p_cursor_str)
    {
        frfree(p_cursor_str);
    }
    if (p_sql)
    {
        frfree(p_sql);
    }
    frdb_statement_free(&p_st_statement);
    postgresql_free_cmd(&p_st_command);
    return APM_L7_ANALYZE_FAIL;
}

/*******************************************************************************
*  FUNC:  解析bind
*  ARGS:  p_st_conn (connect信息)
*      :  p_st_private (postgresql私有数据)
*      :  i_packet_len(packet长度，包括type位+长度位)
*  RTN :  APM_L7_ANALYZE_SUCC       (succ)
*         APM_L7_ANALYZE_TODO       (need more)
*         APM_L7_ANALYZE_FAIL       (fail)
*  NOTE:  i_packet_len必须大于等于与5
*******************************************************************************/
FR_STATIC int __postgresql_parse_bind(Conntrack *p_st_conn
                                    , L7session_postgresql_private *p_st_private
                                    , int i_packet_len)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    int i_format = 0;
    int i_len = 0;
    int i_loop = 0;
    int i_param_count1 = 0;
    int i_param_count2 = 0;
    int i_left_len = i_packet_len - 5;
    L7_fragment_postgresql *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;
    L7_req_postgresql *p_st_req = p_st_private->p_st_req;
    char *p_fromats = NULL;
    char *p_cursor_str = NULL;
    Sql_field_bind *p_lst_bind = NULL;

    /* 长度check */
    if (i_left_len > bytebuff_remaining(p_st_data))
    {
        frdbg("need more data!\n");
        return APM_L7_ANALYZE_TODO;
    }
    /* skip portal string */
    i_ret = postgresql_skip_string(p_st_data, &i_left_len);
    if (i_ret != FR_SUCC)
    {
        frdbg("skip portal string failed!\n");
        return APM_L7_ANALYZE_FAIL;
    }
    /* 取得游标标识字符串 */
    i_ret = postgresql_get_string(p_st_data, &i_left_len, &p_cursor_str);
    if (i_ret != FR_SUCC)
    {
        frdbg("get cursor string failed!\n");
        return APM_L7_ANALYZE_FAIL;
    }

    /* 取得参数个数 */
    i_ret = postgresql_get_short(p_st_data, &i_left_len, &i_param_count1);
    if (i_ret != FR_SUCC || i_param_count1 < 0)
    {
        frdbg("get parameter count failed!\n");
        goto error;
    }
    /* 取得参数formats */
    if (i_param_count1)
    {
        p_fromats = (char *)frmalloc(i_param_count1);
        if (p_fromats == NULL)
        {
            frdbg("malloc failed!\n");
            goto error;
        }
        while (i_loop < i_param_count1)
        {
            i_ret = postgresql_get_short(p_st_data, &i_left_len, &i_format);
            /* format只能是0(text)/1(binary) */
            if (i_ret != FR_SUCC || i_format & 0xFFFFFFFE)
            {
                frdbg("get paramemter type failed!\n");
                goto error;
            }
            p_fromats[i_loop++] = (char)i_format;
        }
    }

    /* 取得参数个数 */
    i_ret = postgresql_get_short(p_st_data, &i_left_len, &i_param_count2);
    if (i_ret != FR_SUCC || i_param_count2 != i_param_count1)
    {
        frdbg("get parameter count failed!\n");
        goto error;
    }
    i_loop = 0;
    /* 创建bind list */
    p_lst_bind = (Sql_field_bind *)frmalloc(sizeof(Sql_field_bind));
    if (p_lst_bind == NULL)
    {
        frdbg("create bind list failed!\n");
        goto error;
    }
    memset(p_lst_bind, 0x0, sizeof(Sql_field_bind));

    /* 解析参数 */
    while (i_loop < i_param_count2)
    {
        i_ret = postgresql_get_int(p_st_data, &i_left_len, &i_len);
        if (i_ret != FR_SUCC)
        {
            frdbg("get paramemter length failed!\n");
            goto error;
        }
        /* 取得一个值 */
        i_ret = psotgresql_get_bind(p_st_data, &i_left_len, i_len
                                    , p_fromats[i_loop], p_lst_bind);
        if (i_ret != FR_SUCC)
        {
            frdbg("get paramemter failed!\n");
            goto error;
        }
        i_loop++;
    }
    if (p_fromats)
    {
        frfree(p_fromats);
        p_fromats = NULL;
    }

    /* skip return formats */
    i_ret = postgresql_get_short(p_st_data, &i_left_len, &i_param_count1);
    if (i_ret != FR_SUCC || i_param_count1 < 0)
    {
        frdbg("get parameter count failed!\n");
        goto error;
    }
    if (i_left_len != i_param_count1 * 2)
    {
        frdbg("format incorrect!\n");
        postgresql_dbg();
        goto error;
    }
    bytebuff_skip(p_st_data, i_left_len);

    /* 更新statement */
    i_ret = __postgresql_update_statement(p_st_conn, p_st_private, &p_cursor_str
                                         , i_packet_len, FR_NO
                                         , p_st_fragment->st_start_timestamp
                                         , p_st_fragment->st_end_timestamp);
    if (i_ret != FR_SUCC)
    {
        frdbg("update statement failed!\n");
        goto error;
    }

    /* 设置bind list */
    if (p_st_req->p_st_command_pre)
    {
        /* add bind list to statement */
        i_ret = frdb_add_resultset_bind(p_st_req->p_st_command_pre->p_st_resultset
                                       , p_lst_bind);
        if (i_ret != FR_SUCC)
        {
            frdbg("add to bind list failed!\n");
            goto error;
        }
    }
    else
    {
        /* just skip */
        frdbg("just skip!\n");
        frdb_field_bind_free(&p_lst_bind);
    }

    if (p_cursor_str)
    {
        frfree(p_cursor_str);
    }
    return APM_L7_ANALYZE_SUCC;

error:
    if (p_fromats)
    {
        frfree(p_fromats);
    }
    if (p_cursor_str)
    {
        frfree(p_cursor_str);
    }
    frdb_field_bind_free(&p_lst_bind);
    return APM_L7_ANALYZE_FAIL;
}

/*******************************************************************************
*  FUNC:  解析describe
*  ARGS:  p_st_conn (connect信息)
*      :  p_st_private (私有信息)
*      :  i_packet_len(packet长度，包括type位+长度位)
*  RTN :  APM_L7_ANALYZE_SUCC       (succ)
*         APM_L7_ANALYZE_TODO       (need more)
*         APM_L7_ANALYZE_FAIL       (fail)
*  NOTE:  i_packet_len必须大于等于与5
*******************************************************************************/
FR_STATIC int __postgresql_parse_describe(Conntrack *p_st_conn
                                        , L7session_postgresql_private *p_st_private
                                        , int i_packet_len)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    uint8_t u8_format = 0;
    int i_left_len = i_packet_len - 5;
    L7_fragment_postgresql *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;
    char *p_cursor_str = NULL;

    /* 长度check */
    if (i_left_len > bytebuff_remaining(p_st_data))
    {
        frdbg("need more data!\n");
        return APM_L7_ANALYZE_TODO;
    }
    /* get describe type */
    i_ret = bytebuff_get_char(p_st_data, &u8_format);
    if (i_ret != FR_SUCC || (u8_format != 'S' && u8_format != 'P'))
    {
        frdbg("format incorrect!\n");
        return APM_L7_ANALYZE_FAIL;
    }
    if (u8_format == 'P')
    {
        bytebuff_skip(p_st_data, i_left_len - 1);
    }
    else
    {
        i_left_len -=  1;
        i_ret = postgresql_get_string(p_st_data, &i_left_len, &p_cursor_str);
        if (i_ret != FR_SUCC || i_left_len != 0)
        {
            return APM_L7_ANALYZE_SUCC;
        }
    }

    /* update statement */
    i_ret = __postgresql_update_statement(p_st_conn, p_st_private
                                         , &p_cursor_str, i_packet_len, FR_NO
                                         , p_st_fragment->st_start_timestamp
                                         , p_st_fragment->st_end_timestamp);
    if (p_cursor_str)
    {
        frfree(p_cursor_str);
    }
    if (i_ret != FR_SUCC)
    {
        frdbg("update statement failed\n");
        return APM_L7_ANALYZE_FAIL;
    }
    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC:  解析execute
*  ARGS:  p_st_conn (connect信息)
*      :  p_st_private (私有信息)
*      :  i_packet_len(packet长度，包括type位+长度位）
*  RTN :  APM_L7_ANALYZE_SUCC       (succ)
*         APM_L7_ANALYZE_TODO       (need more)
*         APM_L7_ANALYZE_FAIL       (fail)
*  NOTE:  i_packet_len必须大于等于与5
*******************************************************************************/
FR_STATIC int __postgresql_parse_execute(Conntrack *p_st_conn
                                       , L7session_postgresql_private *p_st_private
                                       , int i_packet_len)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    int i_left_len = i_packet_len - 5;
    L7_fragment_postgresql *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;
    char *p_cursor_str = NULL;

    /* 长度check */
    if (i_left_len > bytebuff_remaining(p_st_data))
    {
        frdbg("need more data!\n");
        return APM_L7_ANALYZE_TODO;
    }
    i_ret = bytebuff_skip(p_st_data, i_left_len);
    if (i_ret != FR_SUCC)
    {
        frdbg("skip bytes failed!\n");
        return APM_L7_ANALYZE_FAIL;
    }

    /* update statement */
    i_ret = __postgresql_update_statement(p_st_conn, p_st_private, &p_cursor_str
                                         , i_packet_len, FR_YES
                                         , p_st_fragment->st_start_timestamp
                                         , p_st_fragment->st_end_timestamp);
    if (i_ret != FR_SUCC)
    {
        frdbg("update statement failed\n");
        return APM_L7_ANALYZE_FAIL;
    }
    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC:  解析sync
*  ARGS:  p_st_conn (connect信息)
*      :  p_st_private (私有信息)
*      :  i_packet_len(packet长度，包括type位+长度位）
*      :  p_i_end_flg(结束标识)
*  RTN :  APM_L7_ANALYZE_SUCC       (succ)
*         APM_L7_ANALYZE_TODO       (need more)
*         APM_L7_ANALYZE_FAIL       (fail)
*  NOTE:  i_packet_len必须大于等于与5
*******************************************************************************/
FR_STATIC int __postgresql_parse_sync(Conntrack *p_st_conn
                                    , L7session_postgresql_private *p_st_private
                                    , int i_packet_len
                                    , int *p_i_end_flg)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    int i_left_len = i_packet_len - 5;
    L7_fragment_postgresql *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;
    char *p_cursor_str = NULL;

    /* 长度check */
    if (i_left_len > bytebuff_remaining(p_st_data))
    {
        frdbg("need more data!\n");
        return APM_L7_ANALYZE_TODO;
    }
    /* 固定值4 */
    if (i_left_len != 0)
    {
        frdbg("format incorrect\n");
        return APM_L7_ANALYZE_FAIL;
    }
    i_ret = bytebuff_skip(p_st_data, i_left_len);
    if (i_ret != FR_SUCC)
    {
        frdbg("skip bytes failed!\n");
        return APM_L7_ANALYZE_FAIL;
    }

    /* update statement */
    i_ret = __postgresql_update_statement(p_st_conn, p_st_private, &p_cursor_str
                                         , i_packet_len, FR_NO
                                         , p_st_fragment->st_start_timestamp
                                         , p_st_fragment->st_end_timestamp);
    if (i_ret != FR_SUCC)
    {
        frdbg("update statement failed\n");
        return APM_L7_ANALYZE_FAIL;
    }
    *p_i_end_flg = FR_YES;
    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC:  解析query
*  ARGS:  p_st_conn (connect信息)
*      :  p_st_private(私有信息)
*      :  i_packet_len(packet长度，包括type位+长度位）
*      :  p_i_end_flg(结束标识)
*  RTN :  APM_L7_ANALYZE_SUCC       (succ)
*         APM_L7_ANALYZE_TODO       (need more)
*         APM_L7_ANALYZE_FAIL       (fail)
*  NOTE:  i_packet_len必须大于等于与5
*******************************************************************************/
FR_STATIC int __postgresql_parse_query(Conntrack *p_st_conn
                                    , L7session_postgresql_private *p_st_private
                                    , int i_packet_len
                                    , int *p_i_end_flg)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    int i_left_len = i_packet_len - 5;
    unsigned long ul_req_sequence = 0;
    L7_fragment_postgresql *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;
    L7_req_postgresql *p_st_req = p_st_private->p_st_req;
    Sql_resultset *p_st_resultset = NULL;
    Sql_statement *p_st_statement = NULL;
    Postgresql_req_cmd *p_st_command = NULL;
    Frlist_node *p_st_node = NULL;
    char *p_sql = NULL;

    /* 长度check */
    if (i_left_len > bytebuff_remaining(p_st_data))
    {
        frdbg("need more data!\n");
        return APM_L7_ANALYZE_TODO;
    }
    /* 取得sql */
    p_sql = (char *)frmalloc(i_left_len + 1);
    if (p_sql == NULL)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    i_ret = bytebuff_get_bytes(p_st_data, p_sql, i_left_len);
    if (i_ret != FR_SUCC)
    {
        frfree(p_sql);
        return APM_L7_ANALYZE_FAIL;
    }
    p_sql[i_left_len] = '\0';

    /* 创建statement */
    p_st_statement = frdb_create_statement();
    if (p_st_statement == NULL)
    {
        frdbg("create statement failed!\n");
        frfree(p_sql);
        return APM_L7_ANALYZE_FAIL;
    }
    /* 设置sql statement */
    frdb_set_sql(p_st_statement, p_sql);
    p_sql = NULL;
    /* 创建result */
    ul_req_sequence = frct_seq_increase(p_st_conn);
    p_st_resultset = frdb_create_resultset(ul_req_sequence);
    if (p_st_resultset == NULL)
    {
        frdbg("Create sqlbatch resultset failed!\n");
        frdb_statement_free(&p_st_statement);
        return APM_L7_ANALYZE_FAIL;
    }

    /* 创建command */
    p_st_command = (Postgresql_req_cmd *)frmalloc(sizeof(Postgresql_req_cmd));
    if (p_st_command == NULL)
    {
        frdbg("create command failed!\n");
        frdb_statement_free(&p_st_statement);
        frdb_resultset_free(&p_st_resultset);
        return APM_L7_ANALYZE_FAIL;
    }
    memset(p_st_command, 0x0, sizeof(Postgresql_req_cmd));
    p_st_command->i_new_flg = FR_YES;
    p_st_command->p_st_statement = p_st_statement;
    p_st_statement = NULL;
    p_st_command->p_st_resultset = p_st_resultset;
    p_st_resultset = NULL;
    p_st_command->i_packet_len += i_packet_len;
    p_st_command->i_report_flg = FR_YES;
    p_st_command->st_start_timestamp = p_st_fragment->st_start_timestamp;
    p_st_command->st_end_timestamp = p_st_fragment->st_end_timestamp;

    /* 追加到command list中 */
    p_st_node = frlist_node_create(p_st_command);
    if (p_st_node == NULL)
    {
        frdbg("create command list failed!\n");
        postgresql_free_cmd(&p_st_command);
        return APM_L7_ANALYZE_FAIL;
    }
    frlist_push(&p_st_req->st_command_lst, p_st_node);
    p_st_req->p_st_command_pre = p_st_command;

    *p_i_end_flg = FR_YES;
    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC:  解析close
*  ARGS:  p_st_conn (connect信息)
*      :  p_st_private(私有信息)
*      :  i_packet_len(packet长度，包括type位+长度位）
*  RTN :  APM_L7_ANALYZE_SUCC       (succ)
*         APM_L7_ANALYZE_TODO       (need more)
*         APM_L7_ANALYZE_FAIL       (fail)
*  NOTE:  i_packet_len必须大于等于与5
*******************************************************************************/
FR_STATIC int __postgresql_parse_close(Conntrack *p_st_conn
                                    , L7session_postgresql_private *p_st_private
                                    , int i_packet_len)
{
    uint8_t u8_format = 0;
    int i_ret = APM_L7_ANALYZE_SUCC;
    int i_left_len = i_packet_len - 5;
    L7_fragment_postgresql *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;
    L7_req_postgresql *p_st_req = p_st_private->p_st_req;
    char *p_cursor_str = NULL;

    /* 长度check */
    if (i_left_len > bytebuff_remaining(p_st_data))
    {
        frdbg("need more data!\n");
        return APM_L7_ANALYZE_TODO;
    }

    i_ret = bytebuff_get_char(p_st_data, &u8_format);
    if (i_ret != FR_SUCC || (u8_format != 'S' && u8_format != 'P'))
    {
        frdbg("format incorrect!\n");
        return APM_L7_ANALYZE_FAIL;
    }
    if (u8_format == 'P')
    {
        bytebuff_skip(p_st_data, i_left_len - 1);
        /* update statement */
        i_ret = __postgresql_update_statement(p_st_conn, p_st_private, &p_cursor_str
                                             , i_packet_len, FR_NO
                                             , p_st_fragment->st_start_timestamp
                                             , p_st_fragment->st_end_timestamp);
        if (i_ret != FR_SUCC)
        {
            frdbg("update statement failed\n");
            return APM_L7_ANALYZE_FAIL;
        }
        return APM_L7_ANALYZE_SUCC;
    }
    else
    {
        i_left_len -= 1;
        i_ret = postgresql_get_string(p_st_data, &i_left_len, &p_cursor_str);
        if (i_ret != FR_SUCC || i_left_len != 0)
        {
            frdbg("get cursor string failed!\n");
            return APM_L7_ANALYZE_FAIL;
        }
        /* update statement */
        i_ret = __postgresql_update_statement(p_st_conn, p_st_private, &p_cursor_str
                                             , i_packet_len, FR_NO
                                             , p_st_fragment->st_start_timestamp
                                             , p_st_fragment->st_end_timestamp);
        if (p_cursor_str)
        {
            frfree(p_cursor_str);
        }
        if (i_ret != FR_SUCC)
        {
            frdbg("update statement failed\n");
            return APM_L7_ANALYZE_FAIL;
        }
        if (p_st_req->p_st_command_pre)
        {
            p_st_req->p_st_command_pre->i_req_type = POSTGRESQL_TP_CLOSE;
        }
        return APM_L7_ANALYZE_SUCC;
    }
}

/*******************************************************************************
*  FUNC:  解析copy data
*  ARGS:  p_st_conn (connect信息)
*      :  p_st_private(私有信息)
*      :  i_packet_len(packet长度，包括type位+长度位）
*  RTN :  APM_L7_ANALYZE_SUCC       (succ)
*         APM_L7_ANALYZE_TODO       (need more)
*         APM_L7_ANALYZE_FAIL       (fail)
*  NOTE:  i_packet_len必须大于等于与5
*******************************************************************************/
FR_STATIC int __postgresql_parse_cpoy_data(Conntrack *p_st_conn
                                        , L7session_postgresql_private *p_st_private
                                        , int i_packet_len)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    int i_left_len = i_packet_len - 5;
    L7_fragment_postgresql *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;
    char *p_cursor_str = NULL;

    /* 长度check */
    if (i_left_len > bytebuff_remaining(p_st_data))
    {
        frdbg("need more data!\n");
        bytebuff_set_skip(p_st_data, i_left_len - bytebuff_remaining(p_st_data));
        return APM_L7_ANALYZE_TODO;
    }
    bytebuff_skip(p_st_data, i_left_len);

    /* update statement */
    i_ret = __postgresql_update_statement(p_st_conn, p_st_private, &p_cursor_str
                                         , i_packet_len, FR_NO
                                         , p_st_fragment->st_start_timestamp
                                         , p_st_fragment->st_end_timestamp);
    if (i_ret != FR_SUCC)
    {
        frdbg("update statement failed\n");
        return APM_L7_ANALYZE_FAIL;
    }
    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC:  解析copy done
*  ARGS:  p_st_conn (connect信息)
*      :  p_st_private(私有信息)
*      :  i_packet_len(packet长度，包括type位+长度位）
*  RTN :  APM_L7_ANALYZE_SUCC       (succ)
*         APM_L7_ANALYZE_TODO       (need more)
*         APM_L7_ANALYZE_FAIL       (fail)
*  NOTE:  i_packet_len必须大于等于与5
*******************************************************************************/
FR_STATIC int __postgresql_parse_cpoy_done(Conntrack *p_st_conn
                                        , L7session_postgresql_private *p_st_private
                                        , int i_packet_len)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    int i_left_len = i_packet_len - 5;
    L7_fragment_postgresql *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;
    char *p_cursor_str = NULL;

    /* 长度check */
    if (i_left_len > bytebuff_remaining(p_st_data))
    {
        frdbg("need more data!\n");
        return APM_L7_ANALYZE_TODO;
    }
    if (i_left_len != 0)
    {
        frdbg("format incorrect!\n");
        return APM_L7_ANALYZE_FAIL;
    }

    /* update statement */
    i_ret = __postgresql_update_statement(p_st_conn, p_st_private, &p_cursor_str
                                         , i_packet_len, FR_NO
                                         , p_st_fragment->st_start_timestamp
                                         , p_st_fragment->st_end_timestamp);
    if (i_ret != FR_SUCC)
    {
        frdbg("update statement failed\n");
        return APM_L7_ANALYZE_FAIL;
    }
    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC:  解析copy fail
*  ARGS:  p_st_conn (connect信息)
*      :  p_st_private(私有信息)
*      :  i_packet_len(packet长度，包括type位+长度位）
*  RTN :  APM_L7_ANALYZE_SUCC       (succ)
*         APM_L7_ANALYZE_TODO       (need more)
*         APM_L7_ANALYZE_FAIL       (fail)
*  NOTE:  i_packet_len必须大于等于与5
*******************************************************************************/
FR_STATIC int __postgresql_parse_cpoy_fail(Conntrack *p_st_conn
                                        , L7session_postgresql_private *p_st_private
                                        , int i_packet_len)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    int i_left_len = i_packet_len - 5;
    L7_fragment_postgresql *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;
    char *p_cursor_str = NULL;

    /* 长度check */
    if (i_left_len > bytebuff_remaining(p_st_data))
    {
        frdbg("need more data!\n");
        bytebuff_set_skip(p_st_data, i_left_len - bytebuff_remaining(p_st_data));
        return APM_L7_ANALYZE_TODO;
    }
    bytebuff_skip(p_st_data, i_left_len);

    /* update statement */
    i_ret = __postgresql_update_statement(p_st_conn, p_st_private, &p_cursor_str
                                         , i_packet_len, FR_NO
                                         , p_st_fragment->st_start_timestamp
                                         , p_st_fragment->st_end_timestamp);
    if (i_ret != FR_SUCC)
    {
        frdbg("update statement failed\n");
        return APM_L7_ANALYZE_FAIL;
    }
    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC:  解析flush
*  ARGS:  p_st_conn (connect信息)
*      :  p_st_private(私有信息)
*      :  i_packet_len(packet长度，包括type位+长度位）
*  RTN :  APM_L7_ANALYZE_SUCC       (succ)
*         APM_L7_ANALYZE_TODO       (need more)
*         APM_L7_ANALYZE_FAIL       (fail)
*  NOTE:  i_packet_len必须大于等于与5
*******************************************************************************/
FR_STATIC int __postgresql_parse_flush(Conntrack *p_st_conn
                                    , L7session_postgresql_private *p_st_private
                                    , int i_packet_len)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    int i_left_len = i_packet_len - 5;
    L7_fragment_postgresql *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;
    char *p_cursor_str = NULL;

    /* 长度check */
    if (i_left_len > bytebuff_remaining(p_st_data))
    {
        frdbg("need more data!\n");
        return APM_L7_ANALYZE_TODO;
    }
    if (i_left_len != 0)
    {
        frdbg("format incorrect!\n");
        return APM_L7_ANALYZE_FAIL;
    }

    /* update statement */
    i_ret = __postgresql_update_statement(p_st_conn, p_st_private, &p_cursor_str
                                         , i_packet_len, FR_NO
                                         , p_st_fragment->st_start_timestamp
                                         , p_st_fragment->st_end_timestamp);
    if (i_ret != FR_SUCC)
    {
        frdbg("update statement failed\n");
        return APM_L7_ANALYZE_FAIL;
    }
    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC:  解析function
*  ARGS:  p_st_conn (connect信息)
*      :  p_st_private (私有信息)
*      :  i_packet_len(packet长度，包括type位+长度位）
*      :  p_i_end_flg(结束标识)
*  RTN :  APM_L7_ANALYZE_SUCC       (succ)
*         APM_L7_ANALYZE_TODO       (need more)
*         APM_L7_ANALYZE_FAIL       (fail)
*  NOTE:  i_packet_len必须大于等于与5
*******************************************************************************/
FR_STATIC int __postgresql_parse_function(Conntrack *p_st_conn
                                       , L7session_postgresql_private *p_st_private
                                       , int i_packet_len
                                       , int *p_i_end_flg)
{
    int i_len = 0;
    int i_loop = 0;
    int i_obj_id = 0;
    int i_param_count1 = 0;
    int i_param_count2 = 0;
    int i_format = 0;
    int i_ret = APM_L7_ANALYZE_SUCC;
    int i_left_len = i_packet_len - 5;
    unsigned long ul_req_sequence = 0;
    L7_fragment_postgresql *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;
    char *p_sql = NULL;
    char *p_fromats = NULL;
    Sql_field_bind *p_lst_bind = NULL;
    Postgresql_req_cmd *p_st_command = NULL;
    Frlist_node *p_st_node = NULL;
    Sql_statement *p_st_statement = NULL;
    Sql_resultset *p_st_resultset = NULL;
    L7_req_postgresql *p_st_req = p_st_private->p_st_req;

    /* 长度check */
    if (i_left_len > bytebuff_remaining(p_st_data))
    {
        frdbg("need more data!\n");
        return APM_L7_ANALYZE_TODO;
    }

    /* get object ID */
    i_ret = postgresql_get_int(p_st_data, &i_left_len, &i_obj_id);
    if (i_ret != FR_SUCC)
    {
        frdbg("get object ID failed!\n");
        return APM_L7_ANALYZE_FAIL;
    }

    /* 取得参数个数 */
    i_ret = postgresql_get_short(p_st_data, &i_left_len, &i_param_count1);
    if (i_ret != FR_SUCC || i_param_count1 < 0)
    {
        frdbg("get parameter count failed!\n");
        return APM_L7_ANALYZE_FAIL;
    }
    /* 取得参数formats */
    if (i_param_count1)
    {
        p_fromats = (char *)frmalloc(i_param_count1);
        if (p_fromats == NULL)
        {
            frdbg("malloc failed!\n");
            goto error;
        }
        while (i_loop < i_param_count1)
        {
            i_ret = postgresql_get_short(p_st_data, &i_left_len, &i_format);
            /* format只能是0(text)/1(binary) */
            if (i_ret != FR_SUCC || i_format & 0xFFFFFFFE)
            {
                frdbg("get paramemter type failed!\n");
                frfree(p_fromats);
                return APM_L7_ANALYZE_FAIL;
            }
            p_fromats[i_loop++] = (char)i_format;
        }
    }

    /* 取得参数个数 */
    i_ret = postgresql_get_short(p_st_data, &i_left_len, &i_param_count2);
    if (i_ret != FR_SUCC || i_param_count2 != i_param_count1)
    {
        frdbg("get parameter count failed!\n");
        goto error;
    }
    i_loop = 0;
    /* 创建bind list */
    p_lst_bind = (Sql_field_bind *)frmalloc(sizeof(Sql_field_bind));
    if (p_lst_bind == NULL)
    {
        frdbg("create bind list failed!\n");
        goto error;
    }
    memset(p_lst_bind, 0x0, sizeof(Sql_field_bind));

    /* 解析参数 */
    while (i_loop < i_param_count2)
    {
        i_ret = postgresql_get_int(p_st_data, &i_left_len, &i_len);
        if (i_ret != FR_SUCC)
        {
            frdbg("get paramemter length failed!\n");
            goto error;
        }
        /* 取得一个值 */
        i_ret = psotgresql_get_bind(p_st_data, &i_left_len, i_len
                                    , p_fromats[i_loop], p_lst_bind);
        if (i_ret != FR_SUCC)
        {
            frdbg("get paramemter failed!\n");
            goto error;
        }
        i_loop++;
    }
    if (p_fromats)
    {
        frfree(p_fromats);
        p_fromats = NULL;
    }

    /* skip return formats */
    i_ret = postgresql_get_short(p_st_data, &i_left_len, &i_format);
    if (i_ret != FR_SUCC || i_format & 0xFFFFFFFE || i_left_len)
    {
        frdbg("get return format failed!\n");
        goto error;
    }

    /* 创建statement */
    p_st_statement = frdb_create_statement();
    if (p_st_statement == NULL)
    {
        frdbg("create statement failed!\n");
        goto error;
    }
    /* create sql */
    p_sql = (char *)frmalloc(64);
    if (p_sql == NULL)
    {
        frdbg("create statement failed!\n");
        frdb_statement_free(&p_st_statement);
        goto error;
    }
    snprintf(p_sql, 64, "Functioncall %d", i_obj_id);
    /* 设置sql statement */
    frdb_set_sql(p_st_statement, p_sql);
    p_sql = NULL;
    /* 创建result */
    ul_req_sequence = frct_seq_increase(p_st_conn);
    p_st_resultset = frdb_create_resultset(ul_req_sequence);
    if (p_st_resultset == NULL)
    {
        frdbg("Create sqlbatch resultset failed!\n");
        goto error;
    }
    /* add bind list to statement */
    i_ret = frdb_add_resultset_bind(p_st_resultset, p_lst_bind);
    if (i_ret != FR_SUCC)
    {
        frdbg("add to bind list failed!\n");
        goto error;
    }
    p_lst_bind = NULL;

    /* 创建command */
    p_st_command = (Postgresql_req_cmd *)frmalloc(sizeof(Postgresql_req_cmd));
    if (p_st_command == NULL)
    {
        frdbg("create command failed!\n");
        goto error;
    }
    memset(p_st_command, 0x0, sizeof(Postgresql_req_cmd));
    p_st_command->i_new_flg = FR_YES;
    p_st_command->p_st_statement = p_st_statement;
    p_st_statement = NULL;
    p_st_command->p_st_resultset = p_st_resultset;
    p_st_resultset = NULL;
    p_st_command->i_packet_len = i_packet_len;
    p_st_command->i_report_flg = FR_YES;
    p_st_command->st_start_timestamp = p_st_fragment->st_start_timestamp;
    p_st_command->st_end_timestamp = p_st_fragment->st_end_timestamp;

    /* 追加到command list中 */
    p_st_node = frlist_node_create(p_st_command);
    if (p_st_node == NULL)
    {
        frdbg("create command list failed!\n");
        postgresql_free_cmd(&p_st_command);
        return APM_L7_ANALYZE_FAIL;
    }
    frlist_push(&p_st_req->st_command_lst, p_st_node);
    p_st_req->p_st_command_pre = p_st_command;

    *p_i_end_flg = FR_YES;
    return APM_L7_ANALYZE_SUCC;

error:
    if (p_fromats)
    {
        frfree(p_fromats);
    }
    frdb_field_bind_free(&p_lst_bind);
    frdb_statement_free(&p_st_statement);
    frdb_resultset_free(&p_st_resultset);
    return APM_L7_ANALYZE_FAIL;
}

/*******************************************************************************
*  FUNC:  解析request
*  ARGS:  p_st_conn (入力链接信息)
*      :  p_st_hash_report(Frreport_data)
*      :  p_st_private(postgresql私有数据)
*  RTN :  参照module.h
*  NOTE:
*******************************************************************************/
int postgresql_parse_request(Conntrack *p_st_conn
                            , Frhash_header *p_st_hash_report
                            , L7session_postgresql_private *p_st_private)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    int i_end_flg = FR_NO;
    int i_end_conn = FR_NO;
    uint8_t u8_type = 0;
    int i_packet_len = 0;
    int i_req_type = 0;
    char *p_user = NULL;
    char *p_database = NULL;
    L7_session *p_st_session = NULL;
    L7_fragment_postgresql *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;
    Frreport_data *p_st_report_data=NULL;
    char arr_info[128] = {0};

    bytebuff_setPosition(p_st_data, p_st_fragment->i_parsed_position);
    if (p_st_private->p_st_req == NULL)
    {
        /* 取得第一个byte */
        i_ret = bytebuff_peek_char(p_st_data, &u8_type);
        if (i_ret != FR_SUCC)
        {
            frdbg("peek packet type failed!\n");
            return APM_L7_ANALYZE_FAIL;
        }

        /* 首先check是否是StartupPacket/CancelRequest/SSLRequest */
        switch (u8_type)
        {
            case POSTGRESQL_TP_BIND:
            case POSTGRESQL_TP_FUNCTION_CALL:
            case POSTGRESQL_TP_PARSE:
            case POSTGRESQL_TP_PASSWORD_MSG:
            case POSTGRESQL_TP_QUERY:
            case POSTGRESQL_TP_CLOSE:
            case POSTGRESQL_TP_COPY_DATA:
            case POSTGRESQL_TP_COPY_DONE:
            case POSTGRESQL_TP_COPY_FAIL:
            case POSTGRESQL_TP_FLUSH:
            case POSTGRESQL_TP_DESCRIBE:
            case POSTGRESQL_TP_EXECUTE:
            case POSTGRESQL_TP_SYNC:
            case POSTGRESQL_TP_TERMINATE:
                p_st_private->p_st_req = (L7_req_postgresql *)frmalloc(sizeof(L7_req_postgresql));
                if (p_st_private->p_st_req == NULL)
                {
                    frdbg("create request failed!\n");
                    return APM_L7_ANALYZE_FAIL;
                }
                memset(p_st_private->p_st_req, 0x0, sizeof(L7_req_postgresql));
                break;

            default:
                /* 取得长度 */
                i_ret = postgresql_get_int2(p_st_data, &i_packet_len);
                if (i_ret != FR_SUCC || i_packet_len < 4)
                {
                    frdbg("Get Startup packet length failed!\n");
                    return APM_L7_ANALYZE_FAIL;
                }
                /* 根据协议规定CancelRequest长度16 */
                if (i_packet_len == 16)
                {
                    if (bytebuff_remaining(p_st_data) == 12)
                    {
                        i_req_type = POSTGRESQL_TP_CANCEL_REQ;
                    }
                    else
                    {
                        frdbg("formact incorrect!\n");
                        return APM_L7_ANALYZE_FAIL;
                    }
                }
                /* 根据协议规定SSLRequest长度8 */
                else if (i_packet_len == 8)
                {
                    if (bytebuff_remaining(p_st_data) == 4)
                    {
                        i_req_type = POSTGRESQL_TP_SSL_REQ;
                    }
                    else
                    {
                        frdbg("formact incorrect!\n");
                        return APM_L7_ANALYZE_FAIL;
                    }
                }
                /* 其余当做是startup(注:登陆信息不可能有大数据,此处设置2048上限) */
                else if (i_packet_len < 2048)
                {
                    i_ret = __postgresql_parse_startup(p_st_data
                                                      , i_packet_len
                                                      , &p_user
                                                      , &p_database);
                    if (i_ret != APM_L7_ANALYZE_SUCC)
                    {
                        return i_ret;
                    }
                    i_req_type = POSTGRESQL_TP_STARTUP;
                    if (p_st_private->p_st_sess->p_db_name)
                    {
                        frfree(p_st_private->p_st_sess->p_db_name);
                    }
                    if (p_st_private->p_st_sess->p_db_user)
                    {
                        frfree(p_st_private->p_st_sess->p_db_user);
                    }
                    p_st_private->p_st_sess->p_db_name = p_database;
                    p_st_private->p_st_sess->p_db_user = p_user;
                }
                else
                {
                    frdbg("unknow message!\n");
                    return APM_L7_ANALYZE_FAIL;
                }

                /* 创建request */
                p_st_private->p_st_req = (L7_req_postgresql *)frmalloc(sizeof(L7_req_postgresql));
                if (p_st_private->p_st_req == NULL)
                {
                    frdbg("create request failed!\n");
                    return APM_L7_ANALYZE_FAIL;
                }
                memset(p_st_private->p_st_req, 0x0, sizeof(L7_req_postgresql));
                postgresql_init_fragment(p_st_fragment, FR_SRV_IP_PORT);
                p_st_private->p_st_req->i_req_type = i_req_type;
                return APM_L7_ANALYZE_SUCC;
        }
    }

    /* 解析packets */
    while (bytebuff_remaining(p_st_data) >= 5)
    {
        /* 取得packet type */
        i_ret = bytebuff_get_char(p_st_data, &u8_type);
        if (i_ret != FR_SUCC)
        {
            frdbg("get packet type failed!\n");
            return APM_L7_ANALYZE_FAIL;
        }
        /* 取得packet长度 */
        i_ret = postgresql_get_int2(p_st_data, &i_packet_len);
        if (i_ret != FR_SUCC || i_packet_len < 4)
        {
            frdbg("Get packet length failed!\n");
            return APM_L7_ANALYZE_FAIL;
        }

        /*
        *  由于packet长度只是包括自身长度，但是不包括packet type长度，
        *  所以实际长度是取得的packet长度加1
        */
        i_packet_len += 1;
        /* 根据packet type解析packet */
        switch (u8_type)
        {
            /* 解析password(skip) */
            case POSTGRESQL_TP_PASSWORD_MSG:
                i_ret = __postgresql_parse_password(p_st_private
                                                   , i_packet_len
                                                   , &i_end_flg);
                break;

            /* 解析PARSE */
            case POSTGRESQL_TP_PARSE:
                i_ret = __postgresql_parse_parse(p_st_private, i_packet_len);
                break;

            /* 解析BIND */
            case POSTGRESQL_TP_BIND:
                i_ret = __postgresql_parse_bind(p_st_conn
                                               , p_st_private
                                               , i_packet_len);
                break;

            /* 解析DESCRIBE */
            case POSTGRESQL_TP_DESCRIBE:
                i_ret = __postgresql_parse_describe(p_st_conn
                                                   , p_st_private
                                                   , i_packet_len);
                break;

            /* 解析EXECUTE */
            case POSTGRESQL_TP_EXECUTE:
                i_ret = __postgresql_parse_execute(p_st_conn
                                                  , p_st_private
                                                  , i_packet_len);
                break;

            /* 解析SYNC */
            case POSTGRESQL_TP_SYNC:
                i_ret = __postgresql_parse_sync(p_st_conn
                                                , p_st_private
                                                , i_packet_len
                                                , &i_end_flg);
                break;

            /* 解析QUERY */
            case POSTGRESQL_TP_QUERY:
                i_ret = __postgresql_parse_query(p_st_conn
                                                , p_st_private
                                                , i_packet_len
                                                , &i_end_flg);
                break;

            /* 解析CLOSE */
            case POSTGRESQL_TP_CLOSE:
                i_ret = __postgresql_parse_close(p_st_conn
                                                , p_st_private
                                                , i_packet_len);
                break;

            /* 解析COPY DATA */
            case POSTGRESQL_TP_COPY_DATA:
                i_ret = __postgresql_parse_cpoy_data(p_st_conn
                                                    , p_st_private
                                                    , i_packet_len);
                break;

            /* 解析COPY DONE */
            case POSTGRESQL_TP_COPY_DONE:
                i_ret = __postgresql_parse_cpoy_done(p_st_conn
                                                    , p_st_private
                                                    , i_packet_len);
                break;

            /* 解析COPY FAIL */
            case POSTGRESQL_TP_COPY_FAIL:
                i_ret = __postgresql_parse_cpoy_fail(p_st_conn
                                                    , p_st_private
                                                    , i_packet_len);

            /* 解析FLUSH */
            case POSTGRESQL_TP_FLUSH:
                i_ret = __postgresql_parse_flush(p_st_conn
                                                , p_st_private
                                                , i_packet_len);
                break;

            /* 解析FUNCTION CALL */
            case POSTGRESQL_TP_FUNCTION_CALL:
                i_ret = __postgresql_parse_function(p_st_conn
                                                   , p_st_private
                                                   , i_packet_len
                                                   , &i_end_flg);
                break;

            /* 解析TERMINATE */
            case POSTGRESQL_TP_TERMINATE:
                i_end_flg = FR_YES;
                i_end_conn = FR_YES;
                i_ret = APM_L7_ANALYZE_SUCC;
                break;

            default:
                i_ret = APM_L7_ANALYZE_FAIL;
                break;
        }

        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            return i_ret;
        }
        if (i_end_flg == FR_YES)
        {
            if (bytebuff_remaining(p_st_data))
            {
                return APM_L7_ANALYZE_FAIL;
            }
        }
        p_st_fragment->i_parsed_position = bytebuff_getPosition(p_st_data);
    }

    if (i_end_flg == FR_YES)
    {
        if (i_end_conn == FR_YES)
        {
            if (p_st_private->p_st_sess->p_db_user)
            {
                snprintf(arr_info, sizeof(arr_info), "%s logout", p_st_private->p_st_sess->p_db_user);
            }
            else
            {
                snprintf(arr_info, sizeof(arr_info), "logout");
            }
            p_st_report_data = frreport_update_create(p_st_conn
                                , APM_REPORT_UPDATE_LOGOUT
                                , arr_info, &p_st_fragment->st_end_timestamp);
            if (p_st_report_data)
            {
                i_ret = frreport_send(g_p_apm_context, &p_st_report_data);
                if (i_ret != FR_SUCC)
                {
                    return APM_L7_ANALYZE_FAIL;
                }
            }
            p_st_session = frct_get_session(p_st_conn);
            postgresql_session_destroy((void *)(p_st_session->p_session_private));
            p_st_session->p_session_private = NULL;
            return APM_L7_ANALYZE_SUCC;
        }
        //report data
        i_ret = __postgresql_report_req(p_st_conn
                                       , p_st_private
                                       , p_st_hash_report);
        postgresql_init_fragment(p_st_fragment, FR_SRV_IP_PORT);
        return i_ret;
    }
    else
    {
        return APM_L7_ANALYZE_TODO;
    }
}
